package com.fang.dubbo.mock.common;

import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

/**
 * @author fanglingxiao
 * @createDateTime 2022/1/4 8:12 下午
 */
@Slf4j
@Component
public class MyEnvironment {

    @Autowired
    private Environment env;

    public static EnvEnum envEnum = EnvEnum.UNKNOWN;
    private Properties serverProperties = new Properties();
    private static final String SERVER_PROPERTIES_LINUX = "/opt/settings/server.properties";
    private static final String SERVER_PROPERTIES_WINDOWS = "C:/opt/settings/server.properties";

    @PostConstruct
    public void init() {
        initEnv();
    }

    private void initEnv() {
        // load the config settings from file
        loadConfig();

        String currentEnv;
        // 1. try to get environment from JVM system property
        currentEnv = System.getProperty("env");
        if (StrUtil.isNotBlank(currentEnv)) {
            log.info("Environment is set to [{}] by JVM system property 'env'.", currentEnv);
        }

        // 2. try to get environment from spring profile
        if (StringUtils.isBlank(currentEnv)) {
            currentEnv = this.env.getProperty("spring.profiles.active");
            if (StrUtil.isNotBlank(currentEnv)) {
                log.info("Environment is set to [{}] by spring property 'spring.profiles.active'.", currentEnv);
            }
        }

        // 3. try to get environment from OS environment variable
        if (StringUtils.isBlank(currentEnv)) {
            currentEnv = System.getenv("ENV");
            if (StrUtil.isNotBlank(currentEnv)) {
                log.info("Environment is set to [{}] by OS env variable 'env'.", currentEnv);
            }
        }

        // 4. Try to get environment from file "server.properties"
        if (StringUtils.isBlank(currentEnv)) {
            currentEnv = serverProperties.getProperty("env");
            if (StrUtil.isNotBlank(currentEnv)) {
                log.info("Environment is set to [{}] by server.properties 'env'.", currentEnv);
            }
        }


        if (StringUtils.isBlank(currentEnv)) {
            log.error("Environment is not specified from either (1) JVM system property 'env', (2) spring property 'spring.profiles.active', (3) OS env variable 'ENV' nor (4) property 'env' from the server.properties.");
        } else {
            currentEnv = currentEnv.trim();
            envEnum = EnvEnum.parse(currentEnv);
        }

    }

    private void loadConfig() {
        try {
            String path = isOSWindows() ? SERVER_PROPERTIES_WINDOWS : SERVER_PROPERTIES_LINUX;

            File file = new File(path);
            if (file.exists() && file.canRead()) {
                log.info("Loading {}", file.getAbsolutePath());
                FileInputStream fis = new FileInputStream(file);

                try {
                    serverProperties.load(new InputStreamReader(fis, StandardCharsets.UTF_8));
                } finally {
                    fis.close();
                }
            }

        } catch (Throwable ex) {
            log.error("load server.properties failed.", ex);
        }
    }

    public static boolean isOSWindows() {
        String osName = System.getProperty("os.name");
        if (StringUtils.isBlank(osName)) {
            return false;
        }
        return osName.startsWith("Windows");
    }
}
